package com.example.service.impl;

import com.example.config.CaffeineConfig;
import com.example.entity.Admin;
import com.example.service.ICacheService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Random;

/**
 * <p>
 * 缓存测试
 * </p>
 *
 * @author MrWen
 **/
@Slf4j
@Service
public class CacheServiceImpl implements ICacheService {


    /**
     * @Cacheable如果在缓存中找不到计算出的键值，则会调用目标方法，并将返回的值存储在关联的缓存中。
     */
    @Override
    @Cacheable(value = "ADMIN", key = "#id")
    public Admin getById(Long id) {
        Admin admin = Admin.builder()
                .id(id)
                .userName("随机用户" + new Random().nextInt(100))
                .lastLoginTime(LocalDateTime.now())
                .build();

        log.info("detail-->id={},admin={}", id, admin);
        return admin;
        //return null;
    }

    /**
     * 新增或修改一条记录
     *
     * @CachePut注解的作用简单的说一句话：既调用方法，又缓存数据。
     * @cachePut和@Cacheable两个注解都可以用于填充缓存，但使用上略有点差异，
     * @Cacheable注解的执行流程是先在按key在缓存中查找，存在则返回，不存在则执行目标方法，并缓存目标方法的结果。
     * 而@CachePut并不会检查缓存，总是先执行目标方法，并将目标方法的结果保存到缓存中。
     * 实际中比如执行到更新操作时，则希望将最新的数据更新到缓存，如果该方法返回异常，将不再执行保存缓存的逻辑。
     */
    @Override
    @CachePut(value = "ADMIN", key = "#result.id")
    public Admin save(Admin admin) {
        log.info("save-->id={},admin={}", admin.getId(), admin);
        return admin;
    }

    /**
     * 新增或修改一条记录
     */
    @Override
    //@CachePut(value = "ADMIN", key = "#admin.id")
    @CachePut(value = "ADMIN", key = "#admin.id")
    public Admin update(Admin admin) {
        log.info("update-->id={},admin={}", admin.getId(), admin);
        return admin;
    }


    /**
     * 清除一条缓存，key为要清空的数据
     *
     * @CacheEvict该注解的作用根据指定的key或者是allEntries属性值移除缓存中特性的键值对。
     *与@Cacheable相比@CacheEvict注解提供了另外两个属性:
     * allEntries：表示是否清空所有缓存内容，默认false，如果该值为true则清空指定cacheNames缓存块下所有内容，如果指定了allEntries为true，那么再指定key值将没有意义
     * beforeInvocation：是否在执行方法前请空缓存，默认值为false,如果该值为true则在调用目标方法前执行清空缓存，为false的情况下，如果目标方法抛出异常，则不再执行清空缓存逻辑
     */
    @Override
    @CacheEvict(value = "ADMIN", key = "#id")
//    @CacheEvict(value = "admin", allEntries = true) //方法调用后清空所有缓存
//    @CacheEvict(value = "admin", beforeInvocation = true, allEntries = true) //方法调用前清空所有缓存
    public void deleteById(Long id) {
        log.info("deleteById-->id={}", id);
    }
}
